﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

// NotReviewedButNeeded
#pragma once

#include "GcmpDevService.h"
#include "LogBase.h"
#include "OwnerPtr.h"

#pragma warning( push )
#pragma warning( disable : 4251 )

namespace gcmp
{
    class DumpLog;
    class JournalDumpLog;
    class JournalLog;
    class JournalFullLog;
    class ConsistencyDetectLog;

    class GCMP_DEV_SERVICE_EXPORT DumpIntentSetter
    {
    public:
        DumpIntentSetter(int intentDelta);
        ~DumpIntentSetter();
    private:
        int m_intentDelta;
    };

    class GCMP_DEV_SERVICE_EXPORT LogIntentSetter
    {
    public:
        LogIntentSetter(int intentDelta);
        ~LogIntentSetter();
    private:
        int m_intentDelta;
    };

    class GCMP_DEV_SERVICE_EXPORT LogManager
    {
    private:
        LogManager(const std::wstring& subFolderName, const std::wstring& fileNamePrefix, bool numberAutomatically = false);
        bool ValidateLine(LogTypeOfLogManager lmlt, const LogBase * pLogBase, const std::wstring& text) const;

    public:
        ~LogManager(void);

    // Singleton界面
    public:
        // 获取LogManager单例，如果不存在，则先创建。
        // subFolderName如果为空，文件夹格式为“journal+自动编号”。
        // fileNamePrefix如果为空，则和文件夹名字一样。
        // numberJSFile如果为true，则同名.js文件就会添上自动编号，从XXX0001.js到XXX9999.js
        static LogManager* CreateOrGetForWrite(
            const std::wstring& subFolderName = L"",
            const std::wstring& fileNamePrefix = L"",
            bool numberJSFile = false
            );

        // 获取LogManager单例。如果不存在则报错并返回空
        static const LogManager* Get();

        // 查询LogManager单例是否准备好
        static bool IsReady();

    public:
        // 输出到脚本日志
        void WriteLine(LogTypeOfLogManager lmlt, const std::wstring& text, bool copyToCompactedLog = false);

        // 输出到Dump文件
        void DumpLine(const std::wstring& text, bool simplified, bool inOneLine);

        void DumpLineToSpecialFile(const std::wstring& file,const std::wstring& text, bool simplified, bool inOneLine);
        // 输出到Dump文件（没有缩进）
        void DumpLineWithoutIntent(const std::wstring& text);

        // 输出到Dump文件（没有缩进）
        void ConsistencyDetectDumpLine(const std::wstring& text);

        // 输出到脚本日志专属Dump文件
        void JournalDumpLine(const std::wstring& text);

        // 获取Dump缩进大小
        int GetDumpIntentSize() const;

        // 设置Dump缩进大小
        void SetDumpIntentSize(int intentSize);

        // 获取Log缩进大小
        int GetLogIntentSize() const;

        // 设置Log缩进大小
        void SetLogIntentSize(int intentSize);

        // 获取Logs文件夹
        std::wstring GetLogsFolder() const;
        std::wstring GetBaseLogsDirPath() const;

        // 相对Log目录的绝对路径/相对路径转换
        std::wstring GetAbsolutePathForLog(const std::wstring& path) const;
        std::wstring GetRelativePathForLog(const std::wstring& fullPath) const;
    public:
        // 调试用，输出自身状态信息
        void Dump() const;

        // 获取日志
        const JournalFullLog* GetJournalFullLogInstance() const { return m_upJournalFullLogInstance.get(); }

        JournalFullLog* GetJournalFullLogInstance() { return m_upJournalFullLogInstance.get(); }

        DumpLog* GetDumpInstance() { return m_upDumpLogInstance.get(); }

    private:
        static gcmp::OwnerPtr<LogManager> ms_upTheInstance;

        std::wstring m_logsFolder;

        gcmp::OwnerPtr<DumpLog>                     m_upDumpLogInstance;
        gcmp::OwnerPtr<JournalDumpLog>              m_upJournalDumpLogInstance;
        gcmp::OwnerPtr<JournalLog>                  m_upJournalLogInstance;
        gcmp::OwnerPtr<JournalFullLog>              m_upJournalFullLogInstance;
        gcmp::OwnerPtr<ConsistencyDetectLog>        m_upConsistencyDetectLogInstance;
    };
}

#define FYI(text) \
    gcmp::LogManager::CreateOrGetForWrite()->WriteLine(gcmp::LogTypeOfLogManager::FYI, text, false);

#define FYI_IN_BOTH_FULL_AND_COMPACT(text) \
    gcmp::LogManager::CreateOrGetForWrite()->WriteLine(gcmp::LogTypeOfLogManager::FYI, text, true);

#define FYI_IF(condition, text) \
    if(condition) \
    { \
        FYI(text); \
    }

#define DUMP_TO_FILE(file,text) \
    gcmp::LogManager::CreateOrGetForWrite(L"",file,false)->DumpLineToSpecialFile(file,text, false, false);

#define DUMP(text) \
    gcmp::LogManager::CreateOrGetForWrite()->DumpLine(text, false, false);

#define DUMP_IN_ONE_LINE(text) \
    gcmp::LogManager::CreateOrGetForWrite()->DumpLine(text, false, true);

#define DUMP_SIMPLIFIED(text) \
    gcmp::LogManager::CreateOrGetForWrite()->DumpLine(text, true, false);

#define DUMP_SIMPLIFIED_IN_ONE_LINE(text) \
    gcmp::LogManager::CreateOrGetForWrite()->DumpLine(text, true, true);

#define JOURNAL_DUMP(text) \
    gcmp::LogManager::CreateOrGetForWrite()->JournalDumpLine(text);

#define DUMP_NO_INTENT(text) \
    gcmp::LogManager::CreateOrGetForWrite()->DumpLineWithoutIntent(text);
//
#define DUMP_CONSISTENCY_RESULT(text) \
    gcmp::LogManager::CreateOrGetForWrite()->ConsistencyDetectDumpLine(text);
#pragma warning( pop )
